#include <arch.h>
#include <t8.h>
#include <config.h>
#include <i2c.h>
#include <nandflash.h>
#include <util.h>

#if 0
typedef struct {
    unsigned char index;
    unsigned char data;
} LCD_REGS;
// The default values of LCD registers are used.
// So the data below needn't to be set.
static LCD_REGS regDate[] =
{
    {0x0A, 0x01}, //softreset chip first.
    //delay 10ms
    {0x03, 0x05},
    {0x04, 0x3C},
    {0x02, 0x40}, //positive SYNC polarity.
    {0x09, 0xC1},
};
#endif

int Do_InitLcd(void)
{
    int clkval = 0x08;
    int vbpd = 1, vfpd = 1, vspw = 1; // TEST
    int hbpd = 29, hfpd = 9, hspw = 3; // TEST
    unsigned char reg;

    static int init_lcd = 0;

    if (init_lcd) return 0;

    // Enable LDO for LCD
    I2cReadByte(0x92, 0x91, &reg);
    reg &= 0xf0;
    reg |= 0xa; // 2.8V
    I2cWriteByte(0x92, 0x91, reg);

    I2cReadByte(0x92, 0x97, &reg);
    reg |= 0x4; // LDO2
    I2cWriteByte(0x92, 0x97, reg);

    rCLKCON |= 1 << 5; // Enable LCDC clock
    ostdelay(10);

    rGPCCON = (rGPCCON & (~0x3)) | 0x1;
    rGPCUP |= 0x1;
    rGPCDAT |= 0x1;
    ostdelay(1000);
    rGPCDAT &= ~0x1;
    ostdelay(2000);
    rGPCDAT |= 0x1;
    ostdelay(1000);

    rLCDCON1 = ((clkval & 0x3ff) << 8) | (0x3 << 5) | (0xc << 1);
    rLCDCON2 = (vbpd << 24) | ((LCD_HEIGHT - 1) << 14) | (vfpd << 6) | (vspw << 0);
    rLCDCON3 = (hbpd << 19) | ((LCD_WIDTH - 1) << 8) | (hfpd << 0);
    rLCDCON4 = (13 << 8) | (hspw << 0);
    // Bit11: the format of 16bpp, 0: 5551 1: 565
    // Bit10: the polarity of VCLK active edge, 0: falling 1: rising
    // Bit9:  HSYNC pulse polarity, 0: Normal 1: Inverted
    // Bit8:  VSYNC pulse polarity, 0: Normal 1: Inverted
    // Bit7:  video data pulse polarity, 0: Normal 1: Inverted
    // Bit6:  VDEN signal polarity,  0: Normal 1: Inverted
    // Bit5:  PWREN signal polarity, 0: Normal 1: Inverted
    // Bit4:  LEND signal polarity, 0: Normal 1: Inverted
    // Bit3:  LCD_PWREN output signal, 0: Disable 1: Enable
    // Bit2:  LEND output signal, 0: Disable 1: Enable
    // Bit1:  Byte swap control bit, 0: Disable 1: Enable
    // Bit0:  Half-word control bit, 0: Disable 1: Enable
    rLCDCON5 = (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (0 << 7) |
              (0 << 6) | (0 << 5) |  (0 << 4) |  (0 << 3) |  (0 << 2) |
              (0 << 1) | (1 << 0);

    // Framebuffer address
    rLCDSADDR1 = LCD_FRAMEBUFFER >> 1;
    rLCDSADDR2 = (LCD_FRAMEBUFFER + LCD_FRAMEBUFSIZE) >> 1;
    rLCDSADDR3 = (0 << 11) | (LCD_WIDTH << 0);

    rLCDCON1 |= 0x1; // Enable video out

    init_lcd = 1;

    return 0;

}


void write_data_disCxt(int offset, int size, unsigned short data)
{
    unsigned short *pFrame= (unsigned short *)LCD_FRAMEBUFFER;
    if (NULL == pFrame) return ;
    pFrame += offset;

    int i;
    for (i=0; i < size; i++) {
        pFrame[i] = data;
    }
    return ;
}

unsigned int GetBasePlaneBufAddr(void)
{
    return LCD_FRAMEBUFFER;
}

//int ReadLogo(int ptr, int size);
void msleep(unsigned int ms);
extern unsigned char logo[];
extern int bNormalBoot;

void TestColorDisplay()
{
    // 16 bits .test color.
    unsigned short *pBuf = (unsigned short *)LCD_FRAMEBUFFER;
    unsigned short nColorType;
    unsigned short nColorBlue[]  = { 0x0000, 0x0010, 0x001F };
    unsigned short nColorGreen[] = { 0x0000, 0x0400, 0x07E0 };
    unsigned short nColorRed[]   = { 0x0000, 0x8000, 0xF800 };
    int m, n;
    int i, j, k;
    for (i = 0; i < 3; i++) {
        for (j = 0; j < 3; j++) {
            for (k = 0; k < 3; k++) {
                nColorType = nColorRed[k] | nColorBlue[i] | nColorGreen[j];
                for (m = 0; m < LCD_HEIGHT; m++) {
                    for (n = 0; n < LCD_WIDTH; n++) {
                        pBuf[m * LCD_WIDTH + n] = nColorType;
                    }
                }
                ostdelay(1000000);
            }
        }
    }
    return ;
}

void Display_Logo()
{
    Do_ReadKernel((unsigned char*)LCD_FRAMEBUFFER, LOGO_OFFSET, LCD_FRAMEBUFSIZE);
    if(bNormalBoot) {
        //msleep(150);//Wait for lcm init ok
        // backLight_Open();
    }
}
